package org.jeecg.common.util;

import cn.hutool.core.util.StrUtil;
import lombok.NoArgsConstructor;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

import static cn.hutool.core.util.StrUtil.isBlank;

/**
 * @author addzero
 * @since 2022/10/11 11:05 PM
 */
public class TreeSearch {

    public static <T> List<T> getAllLeafNodes(T currentNode, List<T> allNodes, Function<T, String> getIdFun, Function<T, String> getPidFun) {
        List<T> leafNodes = new ArrayList<>();
        leafNodes.add(currentNode); // 添加当前节点

        // 递归查找所有子节点的 T 对象
        for (T childNode : allNodes) {
            if (StrUtil.equals(
                    getPidFun.apply(childNode)
                    ,
                    getIdFun.apply(currentNode)
            )) {
                leafNodes.addAll(getAllLeafNodes(childNode, allNodes, getIdFun, getPidFun));
            }
        }

        return leafNodes;
    }

    /**
     * 递归搜索树保留父节点
     *
     * @param trees 树
     * @param str   str 入参
     * @return
     * @author addzero
     * @since 2022/10/11
     */
    public static <T> void preserveParentNode(List<T> trees, Function<T, List<T>> getChildrenFun, Function<T, String> getSearchBoxFun, String str) {
        if (isBlank(str)) {
            return;
        }
        Stream.iterate(trees.size() - 1, (index) -> --index).limit(trees.size()).forEach(i -> {
            if (!sonIsContainsStr(trees.get(i), getChildrenFun, getSearchBoxFun, str)) {
                trees.remove(i.intValue());
            }
        });
    }

    public static <T> boolean sonIsContainsStr(T node, Function<T, List<T>> getChildrenFun, Function<T, String> getSearchBoxFun, String str) {
        if (node == null) {
            return false;
        }
        return Optional.ofNullable(getChildrenFun.apply(node)).map(children -> {
            final long count =
                    Stream.iterate(children.size() - 1, (index) -> --index).limit(children.size()).filter(i -> {
                        final T childNode = children.get(i);
                        return sonIsContainsStr(childNode, getChildrenFun, getSearchBoxFun, str) || children.remove(i.intValue()) == null;
                    }).count();
            return count > 0 || getSearchBoxFun.apply(node).contains(str);
        }).orElseGet(() -> getSearchBoxFun.apply(node).contains(str));
    }

    //public static Map<Integer, String> getIdNameRelation(List<NameNode> trees, String str) {
    //    final List<NameNode> nameNodes = ListToTreeUtil.tree2List(trees, NameNode::getChildren, NameNode::setChildren);
    //    return nameNodes.stream().filter(e -> Objects.nonNull(e) && Objects.nonNull(e.getName()))
    //            .filter(e -> StringUtils.containsIgnoreCase(e.getName(), str))
    //            .collect(Collectors.toMap(NameNode::getId, NameNode::getName));
    //}

    /**
     * 递归搜索(筛选)树保留父子节点
     *
     * @param trees 树
     * @param str   str 入参
     * @return {@link List }
     * @author addzero
     * @since 2022/10/13
     */
    public static <T> void preserveParentAndChildNode(List<T> trees, Function<T, List<T>> getChildrenFun, Function<T, String> getSearchBoxFun, String str) {
        if (isBlank(str)) {
            return;
        }
        Stream.iterate(trees.size() - 1, (index) -> --index).limit(trees.size()).forEach(i -> {
            if (!sonAndFatherIsContains(trees.get(i), getChildrenFun, getSearchBoxFun, str)) {
                trees.remove(i.intValue());
            }
        });
    }

    /**
     * 父子节点都保留的判断条件
     *
     * @param node 节点
     * @param str  str 入参
     * @return boolean
     * @author zjarlin
     * @since 2023/03/03
     *///好使
    public static <T> boolean sonAndFatherIsContains(T node, Function<T, List<T>> getChildrenFun, Function<T, String> getSearchBoxFun, String str) {
        if (node == null) {
            return false;
        }
        boolean curFlag = StrUtil.containsIgnoreCase(getSearchBoxFun.apply(node), str);
        final List<T> children = getChildrenFun.apply(node);
        if (Objects.nonNull(children)) {
            for (int i = children.size() - 1; i >= 0; i--) {
                final T childNode = children.get(i);
                final boolean childFlag = sonAndFatherIsContains(childNode, getChildrenFun, getSearchBoxFun, str);
                final boolean b = children.stream().noneMatch(e -> StrUtil.containsIgnoreCase(getSearchBoxFun.apply(e), str));
                if (childFlag || b && curFlag) {
                    curFlag = true;
                } else {
                    children.remove(i);
                }
            }
        }

        return curFlag;
    }

    /**
     * 树自定义排序 根节点在前
     *
     * @author zjarlin
     * @see Comparator
     * @since 2023/12/26
     */
    @NoArgsConstructor
    private static class NodeComparator<T> implements Comparator<T> {
        Function<T, String> getPidFun;
        Predicate<T> isRoot = t -> getPidFun.apply(t) == null;

        public NodeComparator(Function<T, String> getPidFun, Predicate<T> isRoot) {
            this.getPidFun = getPidFun;
            this.isRoot = isRoot;
        }

        public NodeComparator(Function<T, String> getPidFun) {
            this.getPidFun = getPidFun;
        }

        @Override
        public int compare(T node1, T node2) {
            // 如果 node1 的 pid 为空，而 node2 的 pid 不为空，则将 node1 排在 node2 前面
            if (isRoot.test(node1) && getPidFun.apply(node2) != null) {
                return -1;
            }
            // 如果 node1 的 pid 不为空，而 node2 的 pid 为空，则将 node2 排在 node1 前面
            else if (getPidFun.apply(node1) != null && isRoot.test(node2)) {
                return 1;
            }
            // 其他情况下，保持原有顺序
            else {
                return 0;
            }
        }

    }

}
